# 封装json提取，数据库提取的方法
import logging
import allure
import re
from abc import ABC,abstractmethod
from utils.send_request import send_jdbc_request
from utils.get_keyword import *

class Extractor(ABC):
    """
    抽象提取器类
    """
    def __init__(self,case,all_vars):
        """
        所有方法都需要的参数
        :param case: 测试用例
        :param all_vars: 全局变量
        """
        self.case = case
        self.all_vars = all_vars

    @abstractmethod
    def extract(self,res):
        pass

    def log_extraction(self,extraction_type,data):
        """
        日志打印抽离
        :param extraction_type:提取器的类型（JDBC提取/JSON提取/正则提取）
        :param data:需要提取的数据
        """
        logging.info(f"4.{extraction_type}，根据{data}提取数据，此时全局变量为{self.all_vars}")

    def add_to_all_vars(self,key,value):
        """
        把数据存入全局变量的方法
        """
        if key in self.all_vars:
            logging.warning(f"提取器：全局变量内的{key}已存在，目前是替换值操作")
        self.all_vars[key] = value

    @staticmethod
    def eval_data(data_str):
        """
        eval封装
        """
        try:
            return eval(data_str) if data_str else None
        except Exception as e:
            logging.error(f"提取器使用eval出错，数据是{data_str},异常是{e}。请检查excel中是否按照字典格式编写")

    @staticmethod
    def re_match_value(pattern,string,index=0):
        """
        处理正则提取表达式
        :param string: 要处理的字符串
        :param pattern: 正则表达式
        :param index: 索引
        :return: 提取出来的值
        """
        matches = [match.group(1) for match in re.finditer(pattern, string)]
        return matches[index]

class JsonExtractor(Extractor):
    """
    JSON提取类
    """
    @allure.step("4.JSON提取")
    def extract(self,res):
        if self.case["jsonExData"]:
            for key, value in self.eval_data(self.case["jsonExData"]).items():
                value = GetKeywords.get_keyword(res, value)
                self.add_to_all_vars(key,value)
            self.log_extraction("JSON提取",self.case["jsonExData"])

class JDBCExtractor(Extractor):
    """
    SQL提取类
    """
    @allure.step("4.SQL提取")
    def extract(self):
        if self.case["sqlExData"]:
            for key, value in self.eval_data(self.case["sqlExData"]).items():
                value = send_jdbc_request(value)[key]
                self.add_to_all_vars(key, value)
            self.log_extraction("SQL提取",self.case["sqlExData"])

class ReExtractor(Extractor):
    """
    正则提取类
    """
    @allure.step("4.正则提取")
    def extract(self,res):
        if self.case["reExData"]:
            for key, value in self.eval_data(self.case["reExData"]).items():
                v = self.re_match_value(value,str(res))
                self.add_to_all_vars(key,v)
            self.log_extraction("正则提取",self.case["reExData"])

# class JsessionidExtractor(Extractor):
#     @allure.step("4.JSESSIONID提取")
#     def extract(self,res):
#         if self.case["jsessionid"]:
#             print("11111111111111")
#             jsessionid = res["JSESSIONID"]
#             print(jsessionid)
#             cookie = "JSESSIONID="+jsessionid
#             print(cookie)
#             self.add_to_all_vars("cookie",cookie)


def perform_extraction(case,all_vars,response):
    """
    遍历所有的提取器对象
    """
    extractions = [
        JsonExtractor(case,all_vars),
        JDBCExtractor(case,all_vars),
        ReExtractor(case,all_vars),
        # JsessionidExtractor(case,all_vars)
    ]
    for extractor in extractions:
        try:
            # 判断对象是正则提取还是JSON提取还是sql提取
            # 正则和JSON提取都需要传入response
            if isinstance(extractor,JsonExtractor) or isinstance(extractor,ReExtractor):
                extractor.extract(response)
            elif isinstance(extractor,JDBCExtractor):
                extractor.extract()
        except Exception as e:
            logging.error(f"在执行{type(extractor).__name__}时发生错误，错误是{e} ")





















